<?php
namespace Home\Controller;

use Utuo\ForegroundController;

class PayController extends ForegroundController {
	
	public function _init() {
		layout('product');
		$this->setModelName("Product");
		$this->setModelControllerName("Product");
		if ( ACTION_NAME != 'notify') {
			$this->checkLogin();
		}
	}
	
	/**
	 * 选择支付方式与银行
	 */
	public function indexAction() {
		$orderId = I("id", 0);
		// 获得接口列表
		$produtPayApiLists = $this->getPayApiList();
		$produtPayApiLists = array_merge($produtPayApiLists, array('COD' =>"货到付款"));
		// 获得订单
		$m = M("ProductOrder");
		$orderId and $order = $m->where("id=%d", $orderId)->find($orderId);
		$this->assign("order", $order);
		$this->assign("productPayApiJSON", json_encode($produtPayApiLists));
		$this->display("{$this->modelControllerName}/payIndex");
	}
	
	/**
	 * 转入支付接口
	 * @param payVo $vo 订单数据
	 */
	public function toPayAction() {
		$orderId = I("id", 0);
		$apitype = I('apitype', ''); // 获得支付方式
		$apiConfig = $this->getApiConfig(array('paymentMethod' => $apitype));
		// 获得订单
		$orderId and $order = D( "My/ProductOrder" )->getOrder($orderId) or $this->error("订单无效($orderId)!");
		$backUrl = $this->getBackUrl($order);
		// 检查重复支付
		if($order['pay_status']) {
			$this->error("已经付过款了。", $backUrl); exit();
		}
		// 处理结算方式
		if($apitype == "COD") {
			M("ProductOrder")->where("id=%d", $orderId)->save( array("order_status" => \My\Model\ProductOrderModel::ORDER_STATUS_SHIPPING, 
																	 "pay_method" => $apitype,
																	 "confirm_time" => time()) );
			$this->success("准备收货吧。", $backUrl); exit();
		} elseif(empty($apitype) or empty($apiConfig)) {
			$this->error("请选择结算方式。"); exit();
		}
		$vo = $this->parseOrder( $order );
		// 支付接口附加参数
		$apiConfig['wparam'] or $apiConfig['wparam'] = array();
		$apiConfig['wparam'] = array_merge($apiConfig['wparam'], array(
			'backUrl' => $backUrl, // 支付成功后的返回页面
		));
		// 支付通知地址
		$apiConfig['notify_url'] = U("Home/Pay/notify", array('sid' => $this->sid, 'apitype' => $apitype), false, true);
		$apiConfig['return_url'] = U("Home/Pay/notify", array('sid' => $this->sid, 'apitype' => $apitype), false, true);
		// 获得支付接口
		$pay = \Utuo\Pay::getInstance($apitype, $apiConfig);
		// 生成支付表单
		$formHtml = $pay->buildRequestForm($vo);
		if ( IS_AJAX ) {
			$this->success("", "", array('payForm'=>$formHtml)); exit();
		} else {
			exit( $formHtml );
		}
	}
	
	/**
	 * 通知回调连接
	 */
	public function notifyAction() {
		$apitype = I('get.apitype', ''); // 获得支付方式
		$pay = \Utuo\Pay::getInstance($apitype, $this->getApiConfig(array('paymentMethod' => $apitype)));
		switch ($apitype) {
			case "Tenpay":
				$paramNames = "sign_type,service_version,input_charset,sign,sign_key_index,trade_mode,trade_state,pay_info,partner,bank_type,bank_billno,total_fee,fee_type,notify_id,transaction_id,out_trade_no,attach,time_end,transport_fee,product_fee,discount,buyer_alias";
				foreach(explode(",", $paramNames) as $v) {
					$notify[$v] = $_REQUEST[$v];
				}
				if( $pay->verifyNotify($notify) ) {
					$this->paySuccess($notify["out_trade_no"], $apitype);
				}
				exit();
			case "WxTenpay":
				if (isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
					// 处理数据
					$notify = (array) simplexml_load_string($GLOBALS['HTTP_RAW_POST_DATA'], 'SimpleXMLElement', LIBXML_NOCDATA);
					if( $pay->verifyNotify($notify) ) {
						$this->paySuccess($notify["out_trade_no"], $apitype);
						exit("<xml><return_code>SUCCESS</return_code></xml>");
					}
				} else {
					exit("<xml><return_code>FAIL</return_code></xml>");
				}
			default:
				exit("<xml><return_code>FAIL</return_code></xml>");
		}
	}
	
	/**
	 * 支付后的返回页面
	 * @param unknown $cfg
	 * @return Ambigous <string, mixed>
	 */
	protected function getBackUrl( $order ) {
		return U("Order/showOrder", "id=".$order['id']."&sid=".$this->sid);
	}
	
	
	/**
	 * 转化为可提交的订单格式
	 * @param unknown $order
	 */
	protected function parseOrder($order) {
		$vo = new \Utuo\Pay\PayVo;
		$vo->setOrderNo($order['order_id']);
		$vo->setFee($order['goods_amount'] + $order['shipping_fee']);
		$body = "";
		foreach ( $order['orderItems'] as $productId => $product  ) {
			$body.= $product['productName']."\r\n";
		}
		$vo->setBody( $body );
		$vo->setTitle("NO:".$order['order_id']);
		return $vo;
	}
	
	/**
	 * 支付成功时
	 * @param unknown $orderId
	 * @param unknown $apitype
	 */
	protected function paySuccess($orderId, $apitype) {
		$productOrder = M("ProductOrder")->where("order_id='%s'", $orderId)->find();
		if ( $productOrder['pay_status'] == \My\Model\ProductOrderModel::PAY_STATUS_NOT_PAID ) {
			M("ProductOrder")->where("id=%d", $productOrder['id'])->save( array("order_status" => \My\Model\ProductOrderModel::ORDER_STATUS_SHIPPING, 
																	 "pay_method" => $apitype, 
																	 "pay_status" => \My\Model\ProductOrderModel::PAY_STATUS_PAID));
		}
	}
	
	/**
	 * 获得支付接口列表
	 * @return multitype:
	 */
	protected function getPayApiList() {
		$d = D("My/ProductPayApi");
		$produtPayApiLists = $d->where("cid=%d and status=1", $this->sid)->getField("tag,name") or $produtPayApiLists = array(); // 获得商家设置的支付接口
		return $produtPayApiLists;
	}
	
	/**
	 * 获得接口配置 
	 * @param unknown $cid
	 * @param unknown $settlementModes
	 * @return array
	 */
	protected function getApiConfig( $cfg ) {
		// 获得支付接口
		$productPayApi = D("ProductPayApi")->where("cid=%d and tag='%s'", $this->cid, $cfg['paymentMethod'])->find(); // 获得支付方式配置
		$config = (array)unserialize($productPayApi['cfg']);
		if ( 'WxTenpay' == $cfg['paymentMethod']) { // 微信支付时读取开发者配置
			$wechat = M('Wechat')->where(array('cid'=>$this->cid))->find();
			$config = array_merge($config, array('appid' => $wechat['appid'], 'appsecret'=> $wechat['appsecret']));
		}
		return $config;
	}
	
}